package query;

import index.HashIndex;
import global.Minibase;
import global.RID;
import global.SearchKey;
import heap.HeapFile;
import parser.AST_Insert;
import relop.Iterator;
import relop.Schema;
import relop.Tuple;

/**
 * Execution plan for inserting tuples.
 */
class Insert implements Plan {

	protected String fileName;
	protected Schema schema;
	protected Object[] values;
	protected String indexName;

	/**
	 * Optimizes the plan, given the parsed query.
	 * 
	 * @throws QueryException
	 *             if table doesn't exists or values are invalid
	 */
	public Insert(AST_Insert tree) throws QueryException {
		// Do some validity check
		fileName = tree.getFileName();
		schema = QueryCheck.tableExists(fileName);
		values = tree.getValues();
		QueryCheck.insertValues(schema, values);
		
		// We need to update index it they exists, so check their validity here
		IndexDesc[] ixDescs = Minibase.SystemCatalog.getIndexes(fileName);
		for(IndexDesc ixDesc : ixDescs) {
			QueryCheck.indexExists(ixDesc.indexName);
		}
	} // public Insert(AST_Insert tree) throws QueryException

	/**
	 * Executes the plan and prints applicable output.
	 */
	public void execute() {
		HeapFile hf = new HeapFile(fileName);
		Tuple tuple = new Tuple(schema, values);
		RID rid = tuple.insertIntoFile(hf);
		
		// If there is index for the table, also update the index
		IndexDesc[] ixDescs = Minibase.SystemCatalog.getIndexes(fileName);
		for(IndexDesc ixDesc : ixDescs) {
			HashIndex indexFile = new HashIndex(ixDesc.indexName);
			indexFile.insertEntry(new SearchKey(tuple.getField(ixDesc.columnName)), rid);
		}
		
		// print the output message
		System.out.println("1 rows inserted.");

	} // public void execute()

} // class Insert implements Plan
